using System;
using System.Xml;
using System.Xml.Xsl;
using InfoJetSoft.Service.Entity;

namespace InfoJetSoft.Service.Util
{
	/// <summary>
	/// Summary description for ExtQueryXsltBuilder.
	/// </summary>
	class QueryXsltBuilder
	{

		public static QueryXslt buildQueryXslt( Manifest manifest, string context, string expression ){
            QueryXslt queryXslt = new QueryXslt();
			queryXslt.Context = context;
			queryXslt.Expression = expression;

			string xslPrefix = manifest.DefaultView.XslPrefix;
				
			if( manifest.QueryXsltTempDoc == null ){
				View view = manifest.DefaultView;
				
				XmlDocument tempDoc = (XmlDocument)view.Doc.CloneNode( true );
				string templateFilter = "//" + NamespaceUtil.toFullName( xslPrefix, "template" );
				XmlNodeList nodeList = DOMUtil.selectNodes( tempDoc, templateFilter, 0, view.NsResolver );
				foreach( XmlNode node in nodeList ){
					node.ParentNode.RemoveChild( node );
				}
				manifest.QueryXsltTempDoc = tempDoc;
			}
	
			int atIndex = context.LastIndexOf( "@" );
			int biasIndex = context.LastIndexOf( "/" );
			XmlDocument xslDoc = null;
			if( atIndex >= 0 && biasIndex >= 0 && atIndex > biasIndex ){
				queryXslt.IsAttribute = true;
				xslDoc = buildAttributeContextXslDoc( manifest, context, expression );
			}else{
				queryXslt.IsAttribute = false;
				xslDoc = buildElementContextXslDoc( manifest, context, expression );
			}
			if( xslDoc == null ){
				return null;
			}

            //CID 0678 //2010.11.03 //Begin
            queryXslt.Transform = new XCTransform(manifest, xslDoc);
            //CID 0678 //2010.11.03 //End
			//CID 0468 //2009.11.26 //Begin
			queryXslt.Xml = xslDoc.OuterXml;
			//CID 0468 //2009.11.26 //End

			return queryXslt;
		}

		private static XmlDocument buildElementContextXslDoc( Manifest manifest, string context, string expression ){
			string xslPrefix = manifest.DefaultView.XslPrefix;
			string rootName = manifest.Template.Doc.DocumentElement.Name;
			
			XmlDocument xslDoc = (XmlDocument)manifest.QueryXsltTempDoc.CloneNode( true );
			
			XmlElement templateElement = (XmlElement) xslDoc.CreateElement( xslPrefix, "template", JetConstant.URI_XSL );
			templateElement.SetAttribute( "match" , rootName );
			xslDoc.DocumentElement.AppendChild( templateElement );
			
			XmlElement resultElement = (XmlElement) xslDoc.CreateElement( "result" );
			templateElement.AppendChild( resultElement );
			
			XmlElement foreachElement = (XmlElement) xslDoc.CreateElement( xslPrefix, "for-each", JetConstant.URI_XSL );
			foreachElement.SetAttribute( "select", context );
			resultElement.AppendChild( foreachElement );
			
			XmlElement fieldElement = (XmlElement) xslDoc.CreateElement( "field" );
			foreachElement.AppendChild( fieldElement );

			XmlElement attrElement = (XmlElement) xslDoc.CreateElement( xslPrefix, "attribute", JetConstant.URI_XSL );
			attrElement.SetAttribute( "name", JetConstant.JetId );
			fieldElement.AppendChild( attrElement );
			
			XmlElement attrValueOfElement = (XmlElement) xslDoc.CreateElement( xslPrefix, "value-of", JetConstant.URI_XSL );
			attrValueOfElement.SetAttribute( "select", "@" + JetConstant.JetId );
			attrElement.AppendChild( attrValueOfElement );
			
			XmlElement fieldValueOfElement = (XmlElement) xslDoc.CreateElement( xslPrefix, "value-of", JetConstant.URI_XSL );
			fieldValueOfElement.SetAttribute( "select", expression );
			fieldElement.AppendChild( fieldValueOfElement );

			return xslDoc;
		}

		private static XmlDocument buildAttributeContextXslDoc( Manifest manifest, string context, string expression ){
			string xslPrefix = manifest.DefaultView.XslPrefix;
			string rootName = manifest.Template.Doc.DocumentElement.Name;
				
			XmlDocument xslDoc = (XmlDocument)manifest.QueryXsltTempDoc.CloneNode( true );
			
			XmlElement templateElement = (XmlElement) xslDoc.CreateElement( xslPrefix, "template", JetConstant.URI_XSL );
			templateElement.SetAttribute( "match" , rootName );
			xslDoc.DocumentElement.AppendChild( templateElement );
			
			XmlElement resultElement = (XmlElement) xslDoc.CreateElement( "result" );
			templateElement.AppendChild( resultElement );
			
			XmlElement foreachElement = (XmlElement) xslDoc.CreateElement( xslPrefix, "for-each", JetConstant.URI_XSL );
			foreachElement.SetAttribute( "select", context );
			resultElement.AppendChild( foreachElement );
			
			XmlElement fieldElement = (XmlElement) xslDoc.CreateElement( "field" );
			foreachElement.AppendChild( fieldElement );

			XmlElement jetAttrElement = (XmlElement) xslDoc.CreateElement( xslPrefix, "attribute", JetConstant.URI_XSL );
			jetAttrElement.SetAttribute( "name", JetConstant.JetId );
			fieldElement.AppendChild( jetAttrElement );
			
			XmlElement jetAttrValueOfElement = (XmlElement) xslDoc.CreateElement( xslPrefix, "value-of", JetConstant.URI_XSL );
			jetAttrValueOfElement.SetAttribute( "select", "../@" + JetConstant.JetId );
			jetAttrElement.AppendChild( jetAttrValueOfElement );

			XmlElement attrAttrElement = (XmlElement) xslDoc.CreateElement( xslPrefix, "attribute", JetConstant.URI_XSL);
			attrAttrElement.SetAttribute( "name", JetConstant.AttributeName );
			fieldElement.AppendChild( attrAttrElement );

			XmlElement attrAttrValueOfElement = (XmlElement) xslDoc.CreateElement( xslPrefix, "value-of", JetConstant.URI_XSL );
			attrAttrValueOfElement.SetAttribute( "select", "name()" );
			attrAttrElement.AppendChild( attrAttrValueOfElement );
			
			XmlElement fieldValueOfElement = (XmlElement) xslDoc.CreateElement( xslPrefix, "value-of", JetConstant.URI_XSL );
			fieldValueOfElement.SetAttribute( "select", expression );
			fieldElement.AppendChild( fieldValueOfElement );

			return xslDoc;
		}

	}
}
